home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / DIBITMAP.PAK / DIBITMAX.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  13KB  |  548 lines

  1. //--------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1995 by Borland International, All rights Reserved
  4. //
  5. // TDiBitmap example program.
  6. //--------------------------------------------------------------------------
  7. #include <owl/pch.h>
  8. #include <owl/applicat.h>
  9. #include <owl/framewin.h>
  10. #include <owl/dibitmap.h>
  11. #include "dibitmap.rh"
  12.  
  13. const int RandomMax = 10;
  14. const int AbsoluteDelta = 6;
  15. #if defined(BI_PLAT_WIN16)
  16. const int NumOfBalls = 1;
  17. #else
  18. const int NumOfBalls = 16;
  19. #endif
  20.  
  21. enum TBltType {
  22.   BCopy,         // Blast whole bitmap up & hope it erases its trail
  23.   BSprite,       // Sprite blt the bitmaps & leave a trail
  24.   BSpriteEraseP, // Sprite blt the bitmaps on a PatBlt cleared dbl buffer
  25.   BSpriteEraseM, // Sprite blt the bitmaps on a memset cleared dbl buffer
  26. };
  27.  
  28. //
  29. // class TSpeedBall
  30. // ~~~~~ ~~~~~~~~~~
  31. class TSpeedBall {
  32.   public:
  33.     // Variables for tracking speed ball position, limit and delta.
  34.     //
  35.     int XLimit;
  36.     int YLimit;
  37.     int XDelta;
  38.     int YDelta;
  39.     int XPos;
  40.     int YPos;
  41.     TDiBitmap*  Bitmap;
  42.  
  43.     operator TRect() {return TRect(XPos,YPos,XPos+Bitmap->Width(),YPos+Bitmap->Height());}
  44.  
  45.     void Move();
  46.     void CopyBlt(TDiBitmap& dstBm);
  47.     void SpriteBlt(TDiBitmap& dstBm);
  48.     void Clear(TDC& dc);
  49. };
  50.  
  51. void TSpeedBall::Move()
  52. {
  53.   XPos += XDelta;
  54.   YPos += YDelta;
  55.  
  56.   if (XPos > XLimit) {
  57.     XPos = XLimit;
  58.     XDelta = -XDelta; //(random(RandomMax) + AbsoluteDelta);
  59.   }
  60.   else if (XPos < 0) {
  61.     XPos = 0;
  62.     XDelta = -XDelta; //random(RandomMax) + AbsoluteDelta;
  63.   }
  64.  
  65.   if (YPos > YLimit) {
  66.     YPos = YLimit;
  67.     YDelta = -YDelta; //(random(RandomMax) + AbsoluteDelta);
  68.   }
  69.   else if (YPos < 0) {
  70.     YPos = 0;
  71.     YDelta = -YDelta; //random(RandomMax) + AbsoluteDelta;
  72.   }
  73. }
  74.  
  75. void TSpeedBall::CopyBlt(TDiBitmap& dstBm)
  76. {
  77.   dstBm.CopyBlt(XPos, YPos, *Bitmap, 0, 0);
  78. }
  79.  
  80. void TSpeedBall::SpriteBlt(TDiBitmap& dstBm)
  81. {
  82.   dstBm.SpriteBlt(XPos, YPos, *Bitmap, 0, 0);
  83. }
  84.  
  85. void TSpeedBall::Clear(TDC& dc)
  86. {
  87.   dc.PatBlt(XPos, YPos, Bitmap->Width(), Bitmap->Height(), BLACKNESS);
  88. }
  89.  
  90. //--------------------------------------------------------------------------
  91.  
  92. //
  93. // class TSpeedCourt
  94. // ~~~~~ ~~~~~~~~~~~
  95. class TSpeedCourt {
  96.   public:
  97.     TSpeedCourt(const TDib& ballDib, int numBalls = 16);
  98.    ~TSpeedCourt();
  99.  
  100.     void Update(TDC& dc);
  101.     void Refresh(TDC& dc);
  102.     void Resize(TSize& newSize);
  103.  
  104.   private:
  105.   public:
  106.     // Speed balls
  107.     //
  108.     TSpeedBall*  Balls;
  109.     int          BallCount;
  110.  
  111.     // State variable for blitting style
  112.     //
  113.     TBltType       BltType;
  114.     TPalette*      Palette;
  115.     TDibDC*        DisplayDC;
  116.     TDiBitmap*     DisplayBitmap;
  117. //    TDiBitmap*     BkgndBitmap;
  118. };
  119.  
  120. //
  121. //
  122. //
  123. TSpeedCourt::TSpeedCourt(const TDib& ballDib, int numBalls)
  124. :
  125.   BallCount(numBalls), Balls(0), Palette(0), DisplayDC(0), DisplayBitmap(0)
  126. {
  127. /*
  128.   BkgndBitmap = new TDiBitmap(_hInstance, TResId(IDB_BKGND));
  129.   {
  130.     TScreenDC dc;
  131.     TDibDC    ddc;
  132.     ddc.SelectObject(*BkgndBitmap);
  133.     ddc.BitBltToScreen(dc, 0,0,800,600);
  134.   }
  135. */
  136.   try {
  137.     Palette  = new TPalette(ballDib);
  138.     DisplayDC = new TDibDC;
  139.  
  140.     Balls = new TSpeedBall[BallCount];
  141.  
  142.     BltType = BCopy;
  143.     for (int i = 0; i < BallCount; i++)
  144.       Balls[i].Bitmap = 0;
  145.  
  146.     TDibDC ballDC;
  147.     for (int i = 0; i < BallCount; i++) {
  148.       Balls[i].Bitmap = new TDiBitmap(ballDib);
  149.       ballDC.SelectObject(*Balls[i].Bitmap);
  150.       ballDC.StretchDIBits(TRect(0, 0, Balls[i].Bitmap->Width(), Balls[i].Bitmap->Height()),
  151.                             TRect(0, 0, Balls[i].Bitmap->Width(), Balls[i].Bitmap->Height()),
  152.                             ballDib);
  153.       Balls[i].XPos = 0;
  154.       Balls[i].YPos = 0;
  155.       Balls[i].XDelta = random(RandomMax) + AbsoluteDelta;
  156.       Balls[i].YDelta = random(RandomMax) + AbsoluteDelta;
  157.     }
  158.   }
  159.   catch (...) {
  160.     throw;
  161.   }
  162. }
  163.  
  164. //
  165. //
  166. //
  167. TSpeedCourt::~TSpeedCourt()
  168. {
  169.   delete Palette;
  170.   delete DisplayDC;
  171.   delete DisplayBitmap;
  172. //  delete BkgndBitmap;
  173.  
  174.   if (Balls) {
  175.     for (int i = 0; i < BallCount; i++)
  176.       delete Balls[i].Bitmap;
  177.     delete[] Balls;
  178.   }
  179. }
  180.  
  181. //
  182. //
  183. //
  184. void TSpeedCourt::Update(TDC& dc)
  185. {
  186.   if (DisplayBitmap) {
  187. //    DisplayDC->SelectPalette(*Palette);
  188. //    DisplayDC->RealizePalette();
  189. //    dc.SelectPalette(*Palette);
  190. //    dc.RealizePalette();
  191.  
  192.     // Just blacken (zero) the bits ourselves
  193.     //
  194.     if (BltType == BSpriteEraseM) {
  195.       memset(DisplayBitmap->GetBits(), 0, DisplayBitmap->Pitch()*DisplayBitmap->Height());
  196.     }
  197.  
  198.     TRect dirty;
  199.     dirty.SetNull();
  200.  
  201.     // Do a first pass over old positions building a dirty rect & erasing each
  202.     // for BSpriteEraseP
  203.     //
  204.     if (BltType == BSpriteEraseP) {
  205. //      TDibDC ddc;
  206. //      ddc.SelectObject(*BkgndBitmap);
  207.       for (int i = 0; i < BallCount; i++) {
  208.         TSpeedBall& b(Balls[i]);
  209.         b.Clear(*DisplayDC);  // Use GDI to clear just this rect
  210. //        DisplayBitmap->CopyBlt(b.XPos, b.YPos, *BkgndBitmap,
  211. //                               b.Bitmap->Width(), b.Bitmap->Height());
  212. //        DisplayDC->BitBlt(b.XPos, b.YPos, b.Bitmap->Width(), b.Bitmap->Height(),
  213. //                          ddc, b.XPos, b.YPos);
  214.       }
  215.     }
  216. #if defined(BI_PLAT_WIN32)
  217.     ::GdiFlush();  // Must flush GDI between GDI and Dib work
  218. #endif
  219.  
  220.     // Do a second pass moving to new positions, building a dirty rect &
  221.     // painting
  222.     //
  223.     for (int i = 0; i < BallCount; i++) {
  224.       TSpeedBall& b(Balls[i]);
  225.       dirty |= b;  // Old position
  226.       b.Move();
  227.       dirty |= b;  // New position
  228.  
  229.       if (BltType == BCopy) {
  230.         b.CopyBlt(*DisplayBitmap);
  231.       }
  232.       else {  // BSprite or BSpriteEraseP or BSpriteEraseM
  233.         b.SpriteBlt(*DisplayBitmap);
  234.       }
  235.     }
  236. #if defined(BI_PLAT_WIN32)
  237.     ::GdiFlush();  // Must flush GDI between GDI and Dib work
  238. #endif
  239.     DisplayDC->BitBltToScreen(dc, dirty.X(), dirty.Y(), dirty.Width(), dirty.Height(), dirty.X(), dirty.Y());
  240.   }
  241. }
  242.  
  243. //
  244. //
  245. //
  246. void TSpeedCourt::Refresh(TDC& dc)
  247. {
  248.   dc.SelectObject(*Palette);
  249.   dc.RealizePalette();
  250.   DisplayDC->BitBltToScreen(dc, 0, 0,
  251.                             DisplayBitmap->Width(), DisplayBitmap->Height());
  252. }
  253.  
  254. //
  255. //
  256. //
  257. void TSpeedCourt::Resize(TSize& newSize)
  258. {
  259.   if (DisplayDC && newSize.cx && newSize.cy) {
  260.     delete DisplayBitmap;
  261.     DisplayBitmap = new TDiBitmap(newSize.cx, newSize.cy, 256);
  262.     DisplayDC->SelectObject(*DisplayBitmap);
  263.  
  264.     DisplayDC->SetDIBColorTable(0, Balls[0].Bitmap->NumColors(),
  265.                                 Balls[0].Bitmap->GetColors());
  266.  
  267. //    DisplayBitmap->CopyBlt(0, 0, *BkgndBitmap);
  268.     DisplayDC->PatBlt(0, 0, newSize.cx, newSize.cy, BLACKNESS);
  269.  
  270.     for (int i = 0; i < BallCount; i++) {
  271.       Balls[i].XLimit = newSize.cx - Balls[i].Bitmap->Width();
  272.       Balls[i].YLimit = newSize.cy - Balls[i].Bitmap->Height();
  273.     }
  274.   }
  275. }
  276.  
  277. //--------------------------------------------------------------------------
  278.  
  279. //
  280. // class TSpeedBallWindow
  281. // ~~~~~ ~~~~~~~~~~~~~~~~
  282. class _USERCLASS TSpeedBallWindow : public TWindow {
  283.   public:
  284.     // Constructors
  285.     //
  286.     TSpeedBallWindow(TWindow* parent);
  287.  
  288.     // Overides
  289.     //
  290.     void SetupWindow();
  291.     void CleanupWindow();
  292.  
  293.     bool IdleAction(long);
  294.     void Paint(TDC&, bool, TRect&);
  295.  
  296.     // Event Handlers
  297.     //
  298.     void EvPaletteChanged(HWND hWndPalChg);
  299.     bool EvQueryNewPalette();
  300.     void EvSize(uint, TSize&);
  301.  
  302.     void CmBlitterBlocks();
  303.     void CeBlitterBlocks(TCommandEnabler&);
  304.     void CmBlitterSprites();
  305.     void CeBlitterSprites(TCommandEnabler&);
  306.     void CmBlitterSpritesEP();
  307.     void CeBlitterSpritesEP(TCommandEnabler&);
  308.     void CmBlitterSpritesEM();
  309.     void CeBlitterSpritesEM(TCommandEnabler&);
  310.  
  311.   private:
  312.     TSpeedCourt Court;
  313.     TClientDC*  ClientDC;
  314.  
  315.   DECLARE_RESPONSE_TABLE(TSpeedBallWindow);
  316. };
  317.  
  318. DEFINE_RESPONSE_TABLE1(TSpeedBallWindow,TWindow)
  319.   EV_COMMAND       (CM_BLOCKS, CmBlitterBlocks),
  320.   EV_COMMAND_ENABLE(CM_BLOCKS, CeBlitterBlocks),
  321.   EV_COMMAND       (CM_SPRITES, CmBlitterSprites),
  322.   EV_COMMAND_ENABLE(CM_SPRITES, CeBlitterSprites),
  323.   EV_COMMAND       (CM_SPRITESEP, CmBlitterSpritesEP),
  324.   EV_COMMAND_ENABLE(CM_SPRITESEP, CeBlitterSpritesEP),
  325.   EV_COMMAND       (CM_SPRITESEM, CmBlitterSpritesEM),
  326.   EV_COMMAND_ENABLE(CM_SPRITESEM, CeBlitterSpritesEM),
  327.   EV_WM_SIZE,
  328.   EV_WM_QUERYNEWPALETTE,
  329.   EV_WM_PALETTECHANGED,
  330. END_RESPONSE_TABLE;
  331.  
  332. //
  333. // TSpeedBallWindow Contructor.  Initializes variables.
  334. //
  335. TSpeedBallWindow::TSpeedBallWindow(TWindow* parent)
  336. :
  337.   TWindow(parent, 0),
  338.   ClientDC(0),
  339.   Court(TDib(GetApplication()->GetInstance(), TResId(IDB_BALL)), NumOfBalls)
  340. {
  341. }
  342.  
  343. //
  344. // Create a client DC for speed
  345. //
  346. void
  347. TSpeedBallWindow::SetupWindow()
  348. {
  349.   TWindow::SetupWindow();
  350.   ClientDC  = new TClientDC(*this);
  351. }
  352.  
  353. void
  354. TSpeedBallWindow::CleanupWindow()
  355. {
  356.   delete ClientDC;
  357.   TWindow::CleanupWindow();
  358. }
  359.  
  360. //
  361. // Activates Palette, then blit's current double buffer.
  362. //
  363. void
  364. TSpeedBallWindow::Paint(TDC& dc, bool, TRect&)
  365. {
  366.   Court.Refresh(dc);
  367. }
  368.  
  369. //
  370. // When nothing needs to be processed step the image then update the
  371. // display.
  372. //
  373. bool
  374. TSpeedBallWindow::IdleAction(long)
  375. {
  376.   Court.Update(*ClientDC);
  377.   return true;  // Suck up as much time as we can get
  378. }
  379.  
  380. //
  381. // When the window size changes, resize the court
  382. //
  383. void
  384. TSpeedBallWindow::EvSize(uint, TSize& newSize)
  385. {
  386.   if (ClientDC && newSize.cx && newSize.cy) {
  387.     Court.Resize(newSize);
  388.     Court.Refresh(*ClientDC);
  389.   }
  390. }
  391.  
  392. //
  393. // Somebody changed the palette. If its not us, then we need to update.
  394. //
  395. void
  396. TSpeedBallWindow::EvPaletteChanged(HWND hWndPalChg)
  397. {
  398.   if (hWndPalChg != GetHandle()) {
  399.     TClientDC clientDC(*this);
  400. #if defined(BI_PLAT_WIN16)
  401.     Court.Palette->UnrealizeObject();
  402. #endif
  403.     clientDC.SelectObject(*Court.Palette, true);
  404.     bool needsUpdate = clientDC.RealizePalette() > 0;
  405.     if (needsUpdate)
  406.       Invalidate(false);
  407.   }
  408. }
  409.  
  410. //
  411. // Activate palette when told by windows.
  412. //
  413. bool
  414. TSpeedBallWindow::EvQueryNewPalette()
  415. {
  416.   if (ClientDC && Court.Palette) {
  417.     ClientDC->SelectObject(*Court.Palette);
  418.     ClientDC->RealizePalette();
  419.   }
  420.  
  421.   return true;
  422. }
  423.  
  424. //
  425. // CM_BLOCKS event response function.
  426. //
  427. void
  428. TSpeedBallWindow::CmBlitterBlocks()
  429. {
  430.   Court.BltType = BCopy;
  431. }
  432.  
  433. //
  434. //
  435. //
  436. void
  437. TSpeedBallWindow::CeBlitterBlocks(TCommandEnabler& ce)
  438. {
  439.   ce.SetCheck((Court.BltType == BCopy) ? TCommandEnabler::Checked :
  440.                                    TCommandEnabler::Unchecked);
  441. }
  442.  
  443. //
  444. // CM_SPRITES event response function.
  445. //
  446. void
  447. TSpeedBallWindow::CmBlitterSprites()
  448. {
  449.   Court.BltType = BSprite;
  450. }
  451.  
  452. //
  453. //
  454. //
  455. void
  456. TSpeedBallWindow::CeBlitterSprites(TCommandEnabler& ce)
  457. {
  458.   ce.SetCheck((Court.BltType == BSprite) ? TCommandEnabler::Checked :
  459.                                      TCommandEnabler::Unchecked);
  460. }
  461.  
  462. //
  463. // CM_SPRITESE event response function.
  464. //
  465. void
  466. TSpeedBallWindow::CmBlitterSpritesEP()
  467. {
  468.   Court.BltType = BSpriteEraseP;
  469. }
  470.  
  471. //
  472. //
  473. //
  474. void
  475. TSpeedBallWindow::CeBlitterSpritesEP(TCommandEnabler& ce)
  476. {
  477.   ce.SetCheck((Court.BltType == BSpriteEraseP) ? TCommandEnabler::Checked :
  478.                                           TCommandEnabler::Unchecked);
  479. }
  480.  
  481. //
  482. // CM_SPRITESEM event response function.
  483. //
  484. void
  485. TSpeedBallWindow::CmBlitterSpritesEM()
  486. {
  487.   Court.BltType = BSpriteEraseM;
  488. }
  489.  
  490. //
  491. //
  492. //
  493. void
  494. TSpeedBallWindow::CeBlitterSpritesEM(TCommandEnabler& ce)
  495. {
  496.   ce.SetCheck((Court.BltType == BSpriteEraseM) ? TCommandEnabler::Checked :
  497.                                           TCommandEnabler::Unchecked);
  498. }
  499.  
  500. //--------------------------------------------------------------------------
  501.  
  502. //
  503. // class TSpeedBallApplication
  504. // ~~~~~ ~~~~~~~~~~~~~~~~~~~~~
  505. // Derived TApplication object for setting TSpeedBallWindow
  506. // as the client.
  507. //
  508. class TSpeedBallApplication : public TApplication {
  509.   public:
  510.     TSpeedBallApplication();
  511.  
  512.     void InitMainWindow();
  513. };
  514.  
  515. //
  516. // Do nothing constructor.
  517. //
  518. TSpeedBallApplication::TSpeedBallApplication()
  519. {
  520. }
  521.  
  522. //
  523. // Set the main window to a TSpeedBallWindow object.
  524. // Assign the menu.
  525. //
  526. void
  527. TSpeedBallApplication::InitMainWindow()
  528. {
  529.   SetMainWindow(new TFrameWindow(0, "TDiBitmap Speed Ball", new TSpeedBallWindow(0)));
  530.   GetMainWindow()->Attr.W = 300;
  531.   GetMainWindow()->Attr.H = 300;
  532.   GetMainWindow()->AssignMenu(IDM_MENU);
  533.   GetMainWindow()->SetIcon(this, IDI_ICON);
  534. }
  535.  
  536. //
  537. // Create and run the TSpeedBallApplication object.
  538. //
  539. int
  540. OwlMain(int /*argc*/, char* /*argv*/[])
  541. {
  542. #if defined(BI_PLAT_WIN16)
  543.   if (!TWinG::IsAvailable())
  544.     throw TXOwl("WinG is not available");
  545. #endif
  546.   return TSpeedBallApplication().Run();
  547. }
  548.